package fun.chutianshu.springsecurity_01.controllers;

import java.util.Objects;

import fun.chutianshu.springsecurity_01.security.JwtUserDetailsService;
import fun.chutianshu.springsecurity_01.util.JwtRequest;
import fun.chutianshu.springsecurity_01.util.JwtResponse;
import fun.chutianshu.springsecurity_01.util.JwtTokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

// 验证控制器
// 通过 /authenticate url 进行用户验证
// 验证成功后会返回 jwt
@RestController
@CrossOrigin
public class JwtAuthenticationController {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private JwtUserDetailsService userDetailsService;

    // 当前接口不被拦截，直接访问，用来验证用户/密码，符合的话，发 token 给客户端
    @RequestMapping(value = "/authenticate", method = RequestMethod.POST)
    public ResponseEntity<?> createAuthenticationToken(@RequestBody JwtRequest authenticationRequest) throws Exception {

        // 调用下面自定义的用户验证方法
        authenticate(authenticationRequest.getUsername(), authenticationRequest.getPassword());

        // 通过自定义的 userDetailsService 用户信息服务类，来验证密码
        // 如果成功，返回 spring security 的用户信息类 UserDetails 对象来存储用户信息
        final UserDetails userDetails = userDetailsService
                .loadUserByUsername(authenticationRequest.getUsername());

        // 通过自定义的 jwt 工具类，使用用户信息对象来生成当前用户的  jwt
        final String token = jwtTokenUtil.generateToken(userDetails);

        return ResponseEntity.ok(new JwtResponse(token));
    }

    // 用户验证方法，接收用户名/密码
    // 不符合要求，抛出异常
    private void authenticate(String username, String password) throws Exception {
        try {
            authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
        }
        // 用户不能使用
        catch (DisabledException e) {
            throw new Exception("USER_DISABLED", e);
        }
        // 未通过验证
        catch (BadCredentialsException e) {
            throw new Exception("INVALID_CREDENTIALS", e);
        }
    }
}
